#ifndef _CLASS_UndoRedoOptimize_INCLUDED_
#define _CLASS_UndoRedoOptimize_INCLUDED_

#include "OpItem.h"
#include "CallBackFunc.h"
#include "SectionFileConfig.h"

#define EmptyObjInTransaction (OBJID_NULL-1)

interface IFileStream;

struct UROptItem
{
	objectid m_oid;
	kOpState m_kState;
	ulong  m_lBeginPos;
	ulong  m_lEndPos;

	UROptItem(objectid oid,kOpState kState,ulong lBeginPos)
		: m_oid(oid)
		, m_kState(kState)
		, m_lBeginPos(lBeginPos)
		, m_lEndPos(lBeginPos)
	{
	}

//only for test begin 
	UROptItem()
		: m_oid(OBJID_NULL)
		, m_kState(kDelete)
		, m_lBeginPos(ulong(-1))
		, m_lEndPos(ulong(-1))
	{
	}

	void Init(objectid oid,kOpState kState,ulong lBeginPos)
	{
		m_oid=oid;	
		m_kState=kState;
		m_lBeginPos=lBeginPos;
		m_lEndPos=lBeginPos;
	}

	void SetEndPos(ulong lEndPos)
	{
		m_lEndPos = (lEndPos + SECTION_FILE_LENGTH) % SECTION_FILE_LENGTH;
	}

	ulong GetOffset() const
	{
		if (m_lEndPos >= m_lBeginPos)
			return m_lEndPos - m_lBeginPos;
		else
			return m_lEndPos - m_lBeginPos + SECTION_FILE_LENGTH;
	}
//only for test end
};

#define MenAllocSize 100
template <class T>
class OptItemDataArray
{
public:
	OptItemDataArray();
	~OptItemDataArray();
public:
	void clear();
	inline int32 GetSize()const;
	T& GetAt(int32 nIndex)const;
	bool Find(objectid oid, int32& nSortIndex)const;
	bool InsertAt(const T& Item, int32 nPos);
	bool RemoveAt(int32 nIndex);
private:
	struct OptItemData
	{
		int32 m_nIndexData;
		T	m_Data;
	public:
		OptItemData()
		{
			m_nIndexData = 0;
		}
	};

private:
	bool Find(objectid oid, int32& nSortIndex, int32 nBegin, int32 nEnd)const;
private:
	OptItemData* m_pDataArray;
	int32 m_nSize;
	int32 m_nMemSize;
};

#define UROptimizeSize	200
class UROptimize
{
public:
	UROptimize();
	~UROptimize();

	int32 AppendItem(const UROptItem& optItem,IFileStream* pIFStream);
	inline int32 GetItemSize()const{return m_nItemSize;}
	inline UROptItem& GetNthItem(int32 nMapIndex, int32 nSortIndex)const{return m_MatrixOptItemMap[nMapIndex].GetAt(nSortIndex);}
	void EnumItems(EnumURItemsCallBack* pFunc)const;
	void Clear();
	
private:
	OptItemDataArray<UROptItem> m_MatrixOptItemMap[UROptimizeSize];
	int32 m_nMapSize[UROptimizeSize];
	int32 m_nItemSize;

	UROptItem m_LastOptItem;
	int32 m_nLastFindPos;
};

class IncOptimize
{
public:
	IncOptimize();
	~IncOptimize();

	int32 InsertItem(const OpItem& optItem);
	int32 AppendItem(const OpItem& optItem);
	inline int32 GetItemSize()const{return m_nItemSize;}
	inline OpItem& GetNthItem(int32 nMapIndex, int32 nSortIndex)const{return m_MatrixOptItemMap[nMapIndex].GetAt(nSortIndex);}
	void EnumItems(EnumIncItemsCallBack* pFunc)const;
	void Clear();
	
private:
	OptItemDataArray<OpItem> m_MatrixOptItemMap[UROptimizeSize];
	int32 m_nMapSize[UROptimizeSize];
	int32 m_nItemSize;

	OpItem m_LastOptItem;
	int32 m_nLastFindPos;
};
#endif	//_CLASS_UndoRedoOptimize_INCLUDED_